首页 / 技术类 / COM / 写个含 Windows Media Player 的窗口

写个含 Windows Media Player 的窗口

2012-09-04 22:16:00

在[上一篇](/2012/09/03/learning_atl_com_interface/)中,我们实现了COM_INTERFACE宏,并且重新写了一个含有WebBrowser的窗口。在那里我们留了中间层OleContainer。为了验证OleContainer的可用性,现在来写一个含有Windows Media Player(下文简称“WMP”)控件的窗口。

WMP控件的容器类除了IOleClientSite、IOleInPlaceSite、IOleInPlaceFrame外,还要实现IDispatch,这些接口的 IXXXImpl 都已经有了,所以做起来就比较方便了:

http://xllib.codeplex.com/SourceControl/changeset/view/19631#315488

 1#include <wmp.h>
 2#include <xl/Win32/COM/Objects/xlOleContainer.h>
 3#include <xl/Win32/COM/InterfaceHelper/xlIDispatchImpl.h>
 4
 5namespace xl
 6{
 7    class MediaPlayerImpl : public OleContainerImpl,
 8                            public IDispatchImpl<>
 9    {
10    public:
11        MediaPlayerImpl() : m_pWMPPlayer(nullptr)
12        {
13
14        }
15
16        ~MediaPlayerImpl()
17        {
18            DestroyMediaPlayer();
19        }
20
21    public:
22        bool CreateMediaPlayer(HWND hWnd, LPCRECT lpRect = nullptr)
23        {
24            DestroyMediaPlayer();
25
26            if (!CreateOleObject(__uuidof(WindowsMediaPlayer)))
27            {
28                return false;
29            }
30
31            if (!InPlaceActive(hWnd, lpRect))
32            {
33                return false;
34            }
35
36            HRESULT hr = m_pOleObj->QueryInterface(__uuidof(IWMPPlayer), (LPVOID *)&m_pWMPPlayer);
37
38            if (FAILED(hr))
39            {
40                return false;
41            }
42
43            return true;
44        }
45
46        void DestroyMediaPlayer()
47        {
48            if (m_pWMPPlayer != NULL)
49            {
50                m_pWMPPlayer->Release();
51                m_pWMPPlayer = nullptr;
52            }
53
54            DestroyOleObject();
55        }
56
57    protected:
58        IWMPPlayer *m_pWMPPlayer;
59    };
60
61    class MediaPlayer : public ComClass<MediaPlayer>,
62                        public MediaPlayerImpl
63    {
64    public:
65        MediaPlayer()
66        {
67
68        }
69
70        ~MediaPlayer()
71        {
72            DestroyMediaPlayer();
73        }
74
75    public:
76        XL_COM_INTERFACE_BEGIN(MediaPlayer)
77            XL_COM_INTERFACE(IOleClientSite)
78            XL_COM_INTERFACE(IOleInPlaceSite)
79            XL_COM_INTERFACE(IOleInPlaceFrame)
80            XL_COM_INTERFACE(IDispatch)
81        XL_COM_INTERFACE_END()
82    };
83
84} // namespace xl

WindowsMediaPlayer这个coclass在wmp.h中定义,OleCreate的时候指定它就可以了。创建好了以后,拿到IWMPPlayer接口,就算完事了,后续的控制可以由该接口完成。

然后,仿照前面的样子写个例程:

#include <xl/Win32/COM/Objects/xlMediaPlayer.h>

class MediaPlayer : public xl::MediaPlayer
{
public:
    void Play(LPCTSTR lpUrl)
    {
        BSTR bstrUrl = SysAllocString(lpUrl);
        m_pWMPPlayer->put_URL(bstrUrl);
        SysFreeString(bstrUrl);
    }
};

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;
}

int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,
                       _In_opt_ HINSTANCE hPrevInstance,
                       _In_ LPTSTR        lpCmdLine,
                       _In_ int           nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    const LPCTSTR CLASS_NAME = _T("MediaPlayerContainer");

    WNDCLASSEX wcex    = { sizeof(WNDCLASSEX) };
    wcex.style         = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc   = WndProc;
    wcex.cbClsExtra    = 0;
    wcex.cbWndExtra    = 0;
    wcex.hInstance     = hInstance;
    wcex.hCursor       = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName = CLASS_NAME;

    RegisterClassEx(&wcex);

    HWND hWnd = CreateWindow(CLASS_NAME,
                             _T("MediaPlayer Sample"),
                             WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                             CW_USEDEFAULT,
                             0,
                             CW_USEDEFAULT,
                             0,
                             nullptr,
                             nullptr,
                             hInstance,
                             nullptr);

    if (hWnd == nullptr)
    {
        return 0;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    RECT rect = {};
    GetClientRect(hWnd, &rect);

    rect.left   += 100;
    rect.top    += 100;
    rect.right  -= 100;
    rect.bottom -= 100;

    MediaPlayer mp;

    if (!mp.CreateMediaPlayer(hWnd, &rect))
    {
        return 0;
    }

    mp.Play(_T("Sample.mid"));

    MSG msg = {};

    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, nullptr, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int)msg.wParam;
}

上面测试了一下创建的时候指定一个矩形区域,看看是否能定位到目标位置。IWMPPlayer的URL属性表示要播放的文件路径或网络地址,设上的时候就会开始播放。运行效果:

以上见MediaPlayerSample.rarhttp://pan.baidu.com/s/1txy2

也可以和GUI类一起使用:

 1#include <xl/Win32/GUI/xlWindow.h>
 2#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
 3
 4class MediaPlayer : public xl::MediaPlayer
 5{
 6public:
 7    void Play(LPCTSTR lpUrl)
 8    {
 9        BSTR bstrUrl = SysAllocString(lpUrl);
10        m_pWMPPlayer->put_URL(bstrUrl);
11        SysFreeString(bstrUrl);
12    }
13};
14
15class MyWindow : public xl::Window
16{
17public:
18    MyWindow()
19    {
20        AppendMsgHandler(WM_DESTROY, MsgHandler(this, &MyWindow::OnDestroy));
21    }
22
23    ~MyWindow()
24    {
25  
26    }
27
28private:
29    LRESULT OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
30    {
31        PostQuitMessage(0);
32        return 0;
33    }
34};
35
36int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,
37                       _In_opt_ HINSTANCE hPrevInstance,
38                       _In_ LPTSTR        lpCmdLine,
39                       _In_ int           nCmdShow)
40{
41    MyWindow wnd;
42  
43    if (!wnd.Create())
44    {
45        return 0;
46    }
47
48    wnd.ShowWindow();
49
50    MediaPlayer mp;
51
52    if (!mp.CreateMediaPlayer(wnd.GetHWND()))
53    {
54        return 0;
55    }
56
57    mp.Play(_T("Sample.mid"));
58
59    MSG msg = {};
60
61    while (GetMessage(&msg, nullptr, 0, 0))
62    {
63        if (!TranslateAccelerator(msg.hwnd, nullptr, &msg))
64        {
65            TranslateMessage(&msg);
66            DispatchMessage(&msg);
67        }
68    }
69
70    return (int)msg.wParam;
71}

以上见MediaPlayerSample2.rarhttp://pan.baidu.com/s/1gdd6YXH

或者作为GUI类的成员:

 1#include <xl/Win32/GUI/xlDialog.h>
 2#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
 3
 4class MediaPlayer : public xl::MediaPlayer
 5{
 6public:
 7    void Play(LPCTSTR lpUrl)
 8    {
 9        BSTR bstrUrl = SysAllocString(lpUrl);
10        m_pWMPPlayer->put_URL(bstrUrl);
11        SysFreeString(bstrUrl);
12    }
13};
14
15class MyDialog : public xl::Dialog
16{
17private:
18    bool OnInitDialog()
19    {
20        if (!m_wmp.CreateMediaPlayer(m_hWnd))
21        {
22            return false;
23        }
24
25        m_wmp.Play(_T("Sample.mid"));
26
27        return true;
28    }
29
30private:
31    MediaPlayer m_wmp;
32};
33
34int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,
35                       _In_opt_ HINSTANCE hPrevInstance,
36                       _In_ LPTSTR        lpCmdLine,
37                       _In_ int           nCmdShow)
38{
39    MyDialog dlg;
40
41    if (!dlg.Create(400, 400))
42    {
43        return 0;
44    }
45
46    dlg.DoModal();
47
48    return 0;
49}

以上见MediaPlayerSample3.rarhttp://pan.baidu.com/s/1gdmuySN

也可以让GUI类继承于它(可能的话,可附加实现WMP的别的COM接口或给出别的对外操作方法):

 1#include <xl/Win32/GUI/xlDialog.h>
 2#include <xl/Win32/COM/Objects/xlMediaPlayer.h>
 3
 4class WMPDialog : public xl::Dialog,
 5                  public xl::MediaPlayer
 6{
 7private:
 8    bool OnInitDialog()
 9    {
10        if (!CreateMediaPlayer(m_hWnd))
11        {
12            return false;
13        }
14
15        return true;
16    }
17
18public:
19    void Play(LPCTSTR lpUrl)
20    {
21        BSTR bstrUrl = SysAllocString(lpUrl);
22        m_pWMPPlayer->put_URL(bstrUrl);
23        SysFreeString(bstrUrl);
24    }
25};
26
27int APIENTRY _tWinMain(_In_ HINSTANCE     hInstance,
28                       _In_opt_ HINSTANCE hPrevInstance,
29                       _In_ LPTSTR        lpCmdLine,
30                       _In_ int           nCmdShow)
31{
32    WMPDialog dlg;
33
34    if (!dlg.Create(400, 400))
35    {
36        return 0;
37    }
38
39    dlg.Play(_T("Sample.mid"));
40    dlg.DoModal();
41
42    return 0;
43}

以上见MediaPlayerSample4.rarhttp://pan.baidu.com/s/1EoZFK

示例的MIDI是我早年蛋疼的时候做的哦,希望大家喜欢。


首发:http://www.cppblog.com/Streamlet/archive/2012/09/04/189470.html



NoteIsSite/0.4